import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;


public class SocketConnections extends Thread{
	Socket soc = null;
	ServerSocket sersoc = null;
	int serverPortNumber;
	Thread receive[] ;
	Thread send[] ;
	ObjectOutputStream objOut = null;
	ObjectInputStream objIn = null;
	FileProperties fileProp;
	PeerData peerData;
	SharedMessageQueue[] sharedMsg;
	CountDownLatch countDown;
	Logger logger;
	
	public SocketConnections(FileProperties fileProp, PeerData peerData, SharedMessageQueue[] sharedMsg, CountDownLatch countDown, Logger logger) {
		// TODO Auto-generated constructor stub
		this.fileProp = fileProp;
		this.peerData = peerData;
		this.sharedMsg = sharedMsg;
		this.countDown = countDown;
		this.logger = logger;
		
		for (int i=0; i<fileProp.peerHostNames.length; i++) {
			try {
				if(fileProp.peerHostNames[i].equals(InetAddress.getLocalHost().getHostAddress())){
					serverPortNumber = fileProp.peerPortNumbers[i];
					break;
				}
			} catch (UnknownHostException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		send = new Thread[fileProp.peerIDArray.length];
		receive = new Thread[fileProp.peerIDArray.length];
	}
	boolean startServerSoc(){
		try {
			sersoc = new ServerSocket(serverPortNumber);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	boolean setSocketConnections(){
		try{
				for(int i=0; i<fileProp.peerIDArray.length; i++){
					if(fileProp.peerIDArray[i] < peerData.getPeerID()){
						soc = new Socket(fileProp.peerHostNames[i], fileProp.peerPortNumbers[i]); //Sending to peers whose ID<peerID
						logger.log("Peer " + peerData.getPeerID() + " makes a connection to Peer " + fileProp.peerIDArray[i] + ". ");						
					}
					else if(fileProp.peerIDArray[i] > peerData.getPeerID()){
						soc = sersoc.accept(); ////Receiving from peers whose ID>peerID
						logger.log("Peer " + peerData.getPeerID() + " is connected from Peer " + fileProp.peerIDArray[i] + ". ");
					}
					else{
						continue;
					}
					
					
					
					/************ generate Streams ************************/
					objIn = new ObjectInputStream(soc.getInputStream());
					objOut = new ObjectOutputStream(soc.getOutputStream());
					
					/************** Initializing shared object queue for this connection **********/
					sharedMsg[i] = new SharedMessageQueue();
					sharedMsg[i].peerID = fileProp.peerIDArray[i];
					
					/************ receiver thread from this peer to all peers ********/
					receive[i] = new ReceiverThread(objIn, peerData, sharedMsg, countDown, fileProp.peerIDArray[i], logger);
					receive[i].start();
					
					/*********** Sender thread from this peer to all peer  *********/
					send[i] = new SenderThread(objOut, sharedMsg[i]);		
					send[i].start();
					
					
				}
				return true;
			}catch(Exception e){
				return false;
			}

	}
	
	public void run(){
		if(!startServerSoc()){
			//ERROR MEssage print
		}
		else{
			if(!setSocketConnections()){
				//ERROR Message print
			}
		}
	}
}
